from PySide6 import QtCore
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QAction
from PySide6.QtWidgets import QTabWidget, QTableWidget, QAbstractItemView, \
    QTableWidgetItem, QMenu, QDockWidget, QMessageBox

from extend_ui.dialog_class import Dialog_Table, Dialog_Combox, Dialog_Edit
from extend_ui.table_class import Table_Center


class Tab_Table(QTabWidget):
    """
    生成Tab栏和所有Table
    1.继承QTabWidget类
    2.父类是主窗口 《重要》 部分关键变量要从父类获取
    3.创建了一个空的QTabWidget 在主窗口上,可添加tab和table
    4.注意父类的关系是：
            MainWindow
            Tab_Table(QTabWidget)
            My_TableWidget(QTableWidget
    """

    signal_clear = QtCore.Signal()      # 清除所有tab的信号

    def __init__(self, parent, config=None):
        super(Tab_Table, self).__init__(parent)
        self.signal_table_info = parent.signal_table_info
        self.table_info = parent.table_info
        self.queue_logging = parent.queue_logging
        self.config = config
        parent.setCentralWidget(self)
        self.init_set()
        # 为中心控件添加一个临时显示table的dock
        self.dock_temp_table = QDockWidget()
        parent.addDockWidget(Qt.RightDockWidgetArea, self.dock_temp_table)
        self.dock_temp_table.setWindowTitle('临时查看')
        self.dock_temp_table.setContextMenuPolicy(Qt.ContextMenuPolicy.NoContextMenu)
        self.dock_temp_table.setFeatures(QDockWidget.DockWidgetClosable)
        self.dock_temp_table.close()

        # 创建变量
        self.table_widgets = {}  # 存储table的字典 {'table': QTable}
        self.tab_list = []  # 用于存储tab栏
        self.temp_table_name = None     # 存储临时表的名字

        self.create_table()

        self.load_config()

        # 关联清除所有tab的信号
        self.signal_clear.connect(self.clear_tab)

        # 如果没有打开的控件就打开第一个
        if not self.tab_list and self.table_widgets:
            name_list = list(self.table_widgets.keys())
            # print(name_list)
            name_list.sort(key=None)
            self.add_widget_to_tab(name_list[0])

    # 添加显示控件
    def add_widget_to_tab(self, name):
        if name in self.tab_list:
            for i in range(len(self.tab_list)):
                if self.tabText(i) == name:
                    self.setCurrentIndex(i)
        else:
            if self.temp_table_name == name:
                self.temp_table_name = None
                self.dock_temp_table.close()
            self.addTab(self.table_widgets[name], name)
            self.tab_list.append(name)
            self.setCurrentIndex(self.tab_list.index(name))

    # 添加表到临时dock
    def add_widget_to_dock(self, name):
        if name in self.tab_list:
            for i in range(len(self.tab_list)):
                if self.tabText(i) == name:
                    self.setCurrentIndex(i)
        else:
            self.temp_table_name = name
            self.dock_temp_table.setWidget(self.table_widgets[name])
            self.dock_temp_table.show()

    # 生成全部的table
    def create_table(self):
        table_name = []
        for i in range(len(self.table_info['type_lv2'])):
            if self.table_info['category_id'][i] + '-' + self.table_info['type_lv2'][i] not in table_name:
                table_name.append(self.table_info['category_id'][i] + '-' + self.table_info['type_lv2'][i])
            # if self.table_info['var_type'][i] in ['5', 'bit'] and self.table_info['action_define'][i]:
            #     table_name.append(self.table_info['type_lv2'][i] + '-' + self.table_info['var_comment'][i])
        for name in table_name:
            widget = Table_Center(table_name=name,
                                  signal_table_info=self.signal_table_info,
                                  signal_clear=self.signal_clear,
                                  table_info=self.table_info,
                                  queue_logging=self.queue_logging)
            self.table_widgets[name] = widget

    # 初始化Tab配置
    def init_set(self):
        self.setTabShape(QTabWidget.Triangular)
        self.setElideMode(Qt.ElideNone)
        self.setTabsClosable(True)
        self.setMovable(True)
        self.setTabBarAutoHide(False)
        self.tabCloseRequested.connect(self.tab_close)

    # 关联移除事件
    def tab_close(self, index):
        self.tab_list.remove(self.tabText(index))
        self.removeTab(index)

    # 清空所有tab
    def clear_tab(self):
        reply = QMessageBox.question(self, '删除', '确认要删除所有控件吗？', QMessageBox.Yes | QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            for i in range(len(self.tab_list)):
                name = self.tab_list.pop()
                self.removeTab(len(self.tab_list))
        else:
            pass

    # 赋值
    def refresh(self):
        """ 根据当前页面刷新数据 """
        curr_widget = self.currentWidget()
        if curr_widget:
            curr_widget.refresh()
        else:
            pass
        # for i in range(len(addrs)):
        #     for widget in list(self.table_widgets.values()):
        #         if str(addrs[i]) in widget.para_addr:
        #             widget.refresh(addrs[i], values[i])

        # for widget in list(self.table_widgets.values()):
        #     widget.refresh(addrs, values)

    # 获取保存的config
    def get_config(self):
        """
        1. tab的名字list
        返回{tab_name: [str, str, str]}
        """
        config_dict = {}
        name_list = []
        for i in range(len(self.tab_list)):
            name_list.append(self.tabText(i))
        config_dict['tab_name'] = name_list
        return config_dict

    # 从配置文件当中自动加载
    def load_config(self):
        if self.config is not None:
            for name in self.config['tab_name']:
                if name in list(self.table_widgets.keys()):
                    self.add_widget_to_tab(name)

    # # 获取当前展示的页面地址
    # def get_current_widget_addr(self):
    #     try:
    #         name = self.tabText(self.currentIndex())
    #         addr_list = self.table_widgets[name].get_current_widget_addr()
    #     except Exception as e:
    #         addr_list = []
    #     return addr_list


# class My_TableWidget(QTableWidget):
#     def __init__(self,
#                  parent=None,
#                  table_name=None,
#                  signal_table_info=Signal(),
#                  signal_clear=Signal(),
#                  table_info=None):
#         super(My_TableWidget, self).__init__(parent)
#         self.table_info = table_info
#         self.table_name = table_name
#         self.signal_table_info = signal_table_info
#         self.signal_clear = signal_clear
#
#         # 获取table的全部数据
#         self.para_addr = []  # 参数地址
#         para_name = []  # 参数名
#         curr_value = []  # 当前值
#         RW_type = []  # 读写类型
#         # 获取真正的表明
#         # name_list = self.table_name.split('-')
#         # table_name= '-'
#         # for i in(range(len(name_list)-1)):
#         #     table_name += name_list[i + 1]
#         # self.table_name = table_name
#         # table_name = self.table_name[self.table_name.index('-')+1:]
#         # self.table_name = table_name
#         # print(self.table_name)
#         # if '-' in self.table_name:
#         #     name1 = self.table_name.split('-')[0]
#         #     name2 = self.table_name.split('-')[1]
#         #     for i in range(len(self.table_info['2级类型'])):
#         #         if self.table_info['2级类型'][i] == name1 and self.table_info['参数名'][i] == name2:
#         #             for j in range(len(self.table_info['选择型操作定义'][i])):
#         #                 self.para_addr.append(str(self.table_info['ADDR'][i]))
#         #                 para_name.append(str(list(self.table_info['选择型操作定义'][i].values())[j]))
#         #                 curr_value.append('0')
#         #                 RW_type.append('Ro')
#         # else:
#         for i in range(len(self.table_info['type_lv2'])):
#             if self.table_name == self.table_info['category_id'][i] + '-' + self.table_info['type_lv2'][i]:
#                 self.para_addr.append(str(self.table_info['addr'][i]))
#                 para_name.append(str(self.table_info['var_comment'][i]))
#                 if self.table_info['var_type'][i] in ['5', 'bit'] and self.table_info['action_define'][i]:
#                     curr_value.append('0x0')
#                 elif self.table_info['var_type'][i] in ['3', 'enum'] and self.table_info['action_define'][i]:
#                     curr_value.append(list(self.table_info['action_define'][i].values())[0])
#                 elif self.table_info['var_type'][i] in ['1', 'int'] and self.table_info['action_define'][i]:
#                     if self.table_info['var_unit'][i]:
#                         curr_value.append('0' + self.table_info['var_unit'][i])
#                     else:
#                         curr_value.append('0')
#                 else:
#                     if self.table_info['var_unit'][i]:
#                         curr_value.append('0.00' + self.table_info['var_unit'][i])
#                     else:
#                         curr_value.append('0.00')
#                 if self.table_info['isWritable'][i] == 1:
#                     RW_type.append('R/W')
#                 else:
#                     RW_type.append('Ro')
#         # 设置table参数
#         self.setRowCount(len(self.para_addr))  # 设置行数
#         self.setColumnCount(4)  # 设置列数
#         self.verticalHeader().setVisible(False)  # 设置表头状态
#         self.setHorizontalHeaderLabels(['参数地址', '参数名称', '当前值（单位）', '类型'])  # 设置列名
#         self.setEditTriggers(QAbstractItemView.NoEditTriggers)  # 禁止编辑
#         self.setSelectionBehavior(QAbstractItemView.SelectRows)  # 设置选择行为为单行
#
#         # if '-' in self.table_name:
#         #     pass
#         # else:
#         self.cellDoubleClicked.connect(self.double_clicked)
#         self.setContextMenuPolicy(Qt.CustomContextMenu)
#         self.customContextMenuRequested.connect(self.right_clicked)
#
#         # 将数据添加到表格
#         for i in range(len(self.para_addr)):
#             tableitem1 = QTableWidgetItem(self.para_addr[i])
#             tableitem1.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
#             tableitem2 = QTableWidgetItem(para_name[i])
#             tableitem2.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
#             tableitem3 = QTableWidgetItem(curr_value[i])
#             tableitem3.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
#             tableitem4 = QTableWidgetItem(RW_type[i])
#             tableitem4.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
#             self.setItem(i, 0, tableitem1)
#             self.setItem(i, 1, tableitem2)
#             self.setItem(i, 2, tableitem3)
#             self.setItem(i, 3, tableitem4)
#
#     # 绑定双击事件
#     def double_clicked(self, row, col):
#         if col == 2:
#             para_addr = int(self.item(row, 0).text())
#             if self.table_info['var_type'][para_addr] in ['5', 'bit'] and self.table_info['action_define'][para_addr]:
#                 dialog_table = Dialog_Table(self)
#                 dialog_table.display(para_addr)
#             elif self.table_info['var_type'][para_addr] in ['3', 'enum']  and self.table_info['action_define'][para_addr]:
#                 dialog_combox = Dialog_Combox(self)
#                 dialog_combox.display(para_addr)
#             else:
#                 dialog_edit = Dialog_Edit(self)
#                 dialog_edit.display(para_addr)
#
#     # 绑定右键事件
#     def right_clicked(self, pos):
#         # 判断是否点击了item
#         if pos.x() < 400 and pos.y() < len(self.para_addr) * 30:
#             if self.currentItem().column() == 1:
#                 real_addr = int(self.item(self.currentItem().row(), 0).text())
#                 menu_button = QMenu(self)
#                 menu_pull_button = QMenu(self)
#                 menu_button_group = QMenu(self)
#                 menu_textline = QMenu(self)
#                 add_button_on_off = menu_button.addAction('添加按钮')
#                 add_combox_on_off = menu_button.addAction('添加单选框')
#                 add_pull_button = menu_pull_button.addAction('添加按钮')
#                 add_pull_combox = menu_pull_button.addAction('添加单选框')
#                 add_buttons = menu_button_group.addAction('添加一组按钮')
#                 add_textline = menu_textline.addAction('添加输入框')
#                 # 弹出对应菜单
#                 if self.table_info['var_type'][real_addr] in ['5', 'bit']:
#                     if self.table_info['action_define'][real_addr]:
#                         action = menu_button_group.exec_(self.mapToGlobal(pos))
#                     else:
#                         action = menu_textline.exec_(self.mapToGlobal(pos))
#                 elif self.table_info['var_type'][real_addr] in ['3', 'enum']:
#                     if not self.table_info['action_define'][real_addr]:
#                         action = menu_textline.exec_(self.mapToGlobal(pos))
#                     elif list(self.table_info['action_define'][real_addr].values())[0] == '禁止' or \
#                             list(self.table_info['action_define'][real_addr].values())[0] == 'off' or \
#                             list(self.table_info['action_define'][real_addr].values())[0] == 'no':
#                         action = menu_button.exec_(self.mapToGlobal(pos))
#                     else:
#                         action = menu_pull_button.exec_(self.mapToGlobal(pos))
#                 else:
#                     action = menu_textline.exec_(self.mapToGlobal(pos))
#
#                 # 点击菜单作出响应判断
#                 if action == add_buttons:
#                     self.signal_table_info.emit(3, [real_addr], [None])
#                 elif action == add_button_on_off:
#                     self.signal_table_info.emit(3, [real_addr], [None])
#                 elif action == add_combox_on_off:
#                     self.signal_table_info.emit(4, [real_addr], [None])
#                 elif action == add_pull_button:
#                     self.signal_table_info.emit(3, [real_addr], [None])
#                 elif action == add_pull_combox:
#                     self.signal_table_info.emit(4, [real_addr], [None])
#                 elif action == add_textline:
#                     self.signal_table_info.emit(5, [real_addr], [None])
#             else:
#                 pass
#
#         else:
#             action = QAction("Delete ALL", self)
#             action.triggered.connect(self.delete_all_table)
#             menu = QMenu(self)
#             menu.addAction(action)
#             menu.exec(self.mapToGlobal(pos))
#
#     def delete_all_table(self):
#         self.signal_clear.emit()
#
#     # 赋值
#     def refresh(self):
#         """ 通过上层获取当前显示的页面，并只刷新当前页面显示的所有变量 值来自于table_info的当前值 """
#         for i in range(len(self.para_addr)):
#             addr = int(self.para_addr[i])
#             curr_value = self.table_info['var_current'][addr]
#             if self.table_info['var_type'][addr] in ['bit', '5']:
#                 self.item(i, 2).setText(hex(int(curr_value)))
#             elif self.table_info['var_type'][addr] in ['enum', '3'] and self.table_info['action_define'][addr]:
#                 if str(int(curr_value)) in self.table_info['action_define'][addr].keys():
#                     self.item(i, 2).setText(self.table_info['action_define'][addr][str(int(curr_value))])
#                 else:
#                     self.item(i, 2).setText(str(int(curr_value)))
#             elif self.table_info['var_type'][addr] in ['int', '1']:
#                 self.item(i, 2).setText(str(curr_value) + self.table_info['var_unit'][addr])
#             else:
#                 if 0.0 < abs(curr_value) < 0.01:
#                     self.item(i, 2).setText(
#                         '{:.2e}'.format(curr_value) + self.table_info['var_unit'][addr])
#                 elif curr_value > 100000:
#                     self.item(i, 2).setText(
#                         '{:.4e}'.format(curr_value) + self.table_info['var_unit'][addr])
#                 else:
#                     if self.table_info['var_decimal'][addr]:
#                         self.item(i, 2).setText(
#                             ('%.' + self.table_info['var_decimal'][addr] + 'f' % curr_value) + self.table_info['var_unit'][
#                                 addr])
#                     else:
#                         self.item(i, 2).setText(
#                             ('%.2f' % curr_value) + self.table_info['var_unit'][addr])

    # # 获取需要刷新的全部地址
    # def get_current_widget_addr(self):
    #     list_addr = []
    #     for addr in self.para_addr:
    #         list_addr.append(int(addr))
    #     return list_addr
